#include "ChannelFactory.h"
#include "SerialPort.h"
#include "ClientSocket.h"
#include "ServerSocket.h"
#include "Directory.h"
#include "Codecs.h"

ChannelFactory::ChannelFactory()
{
    _manufacturer.insert("Serial"      , &ChannelFactory::CreateSerial);
    _manufacturer.insert("ClientSocket", &ChannelFactory::CreateClientSocket);
    _manufacturer.insert("ServerSocket", &ChannelFactory::CreateServerSocket);
    _manufacturer.insert("Directory"   , &ChannelFactory::CreateDataDirectory);
}

ChannelFactory& ChannelFactory::Instance()
{
    static ChannelFactory factory;
    return factory;
}

ChannelFactory::Channel ChannelFactory::CreateChannel(const QString& type, const StringMap& settings)
{
    _settings = settings;
    return _manufacturer.contains(type) ? (this->*_manufacturer[type])() : ChannelFactory::Channel();
}

QStringList ChannelFactory::GetChannelTypes()
{
    return _manufacturer.keys();
}

ISimpleChannelPtr ChannelFactory::CreateDataDirectory()
{
    DirectorySettings settings;

    settings.path               = Decode("CP1251", GetChannelOption("path", "").toByteArray()); 
    settings.extension          = GetChannelOption("extension", "dat").toString();
    settings.filemask           = GetChannelOption("mask", "*.*").toString();
    settings.createIfDontExist  = GetChannelOption("createIfDontExist", "false").toBool();
    settings.isNamingArbitrary  = GetChannelOption("arbitraryNaming", "true").toBool();
    settings.autodel            = GetChannelOption("autodel", "true").toBool();
    settings.active             = GetChannelOption("active", "false").toBool();

    return ISimpleChannelPtr(new Directory(settings));
}

ISimpleChannelPtr ChannelFactory::CreateSerial()
{
    PortSettings settings;

	int baudrate     = GetChannelOption("baudrate"   ,     "9600").toInt();
	int databits     = GetChannelOption("databits"   ,        "8").toInt();
	int stopbits     = GetChannelOption("stopbits"   ,        "1").toInt();
	QString parity   = GetChannelOption("parity"     ,     "NONE").toString();
	QString flow     = GetChannelOption("flowcontrol", "FLOW_OFF").toString();
	QString name     = GetChannelOption("port"       ,     "COM1").toString();
    int millisec     = GetChannelOption("millisec"   ,      "100").toInt();

	settings.BaudRate         = BaudRate(baudrate);
	settings.DataBits         = DataBits(databits);
	settings.Parity           = Parity(parity);
	settings.StopBits	      = StopBits(stopbits);
	settings.FlowControl      = Flow(flow);
    settings.Timeout_Millisec = millisec;

    return ISimpleChannelPtr(new Serial(settings, name));
}

ISimpleChannelPtr ChannelFactory::CreateClientSocket()
{
    SocketSettings settings;

    settings.host    = GetChannelOption("host", "localhost").toString();
    settings.port    = GetChannelOption("port",      "1027").toUInt();
    settings.timeout = GetChannelOption("timeout",   "5000").toUInt();

    return ISimpleChannelPtr(new ClientSocket(settings));
}

ISimpleChannelPtr ChannelFactory::CreateServerSocket()
{
    SocketSettings settings;

	settings.host    = GetChannelOption("host", "localhost").toString();
	settings.port    = GetChannelOption("port",      "1028").toUInt();
    settings.timeout = GetChannelOption("timeout",   "5000").toUInt();

    return ISimpleChannelPtr(new ServerSocket(settings));
}

QVariant ChannelFactory::GetChannelOption(const QString& key, const QVariant& def)
{
    return _settings.contains(key) ? _settings[key] : def; 
}
